import logging

from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session

from apps.tab_manage.models import Group, WebURL
from apps.tab_manage.response_model import GetIconRequest, UrlData, URLUpdate
from apps.tab_manage.utils import get_favicon_url

from common.response.response_code import CustomResponseCode as HttpCode
from common.response.response_schema import response_base, simple_response
from database.db_sql import get_db

router = APIRouter()


@router.post('/get_icon')
async def get_url_icon(url_request: GetIconRequest):
    url_icon = get_favicon_url(url_request.url)
    if url_icon is None:
        return simple_response(code=400, msg="无效URL或网络受限")
    return simple_response(data=url_icon)


@router.post('')
async def add_url(url_data: UrlData, db: AsyncSession = Depends(get_db)):
    async with db.begin():
        group = await db.execute(select(Group).where(Group.id == url_data.group_id))
        group = group.scalar_one_or_none()
        if group is None:
            return simple_response(code=400, msg="无效分组ID")

        icon = url_data.icon.strip() if url_data.icon else None
        sort_order = int(url_data.sort_order) if url_data.sort_order or str(url_data.sort_order).isdigit() else 0

        new_url = WebURL(
            url=url_data.url,
            name=url_data.name,
            icon=icon,
            description=url_data.description,
            sort_order=sort_order,
            group_id=url_data.group_id
        )

        try:
            db.add(new_url)
            await db.commit()  # 提交事务
        except Exception as e:
            logging.error(f"添加出错: {e}")
            await db.rollback()  # 回滚事务
            return simple_response(code=500, msg="添加失败")

    return simple_response(code=201, data=new_url)


@router.put('/{url_id}')
async def update_url(url_id: int, url_data: URLUpdate, db: AsyncSession = Depends(get_db)):
    async with db.begin():
        existing_url = await db.execute(select(WebURL).where(WebURL.id == url_id))
        existing_url = existing_url.scalar_one_or_none()

        if not existing_url:
            return simple_response(code=404)

        if url_data.url is not None:
            existing_url.url = url_data.url
        if url_data.name is not None:
            existing_url.name = url_data.name
        if url_data.icon is not None:
            existing_url.icon = url_data.icon
        if url_data.description is not None:
            existing_url.description = url_data.description
        if url_data.sort_order is not None:
            existing_url.sort_order = url_data.sort_order
        if url_data.group_id is not None:
            existing_url.group_id = url_data.group_id

        await db.commit()
        return simple_response(code=200, data=existing_url)


@router.delete('/{url_id}')
async def delete_url(url_id: int, db: AsyncSession = Depends(get_db)):
    async with db.begin():
        url = await db.execute(select(WebURL).where(WebURL.id == url_id))
        url = url.scalar_one_or_none()

        if not url:
            return simple_response(code=404)

        await db.delete(url)
        await db.commit()

    return simple_response(code=204)


@router.get('')
async def get_urls(db: AsyncSession = Depends(get_db)):
    async with db.begin():
        urls = await db.execute(select(WebURL).order_by(WebURL.sort_order, WebURL.id))
        urls = urls.scalars().all()

    return simple_response(data=[u for u in urls])


@router.get('/group/{group_id}')
async def get_urls_by_group(group_id: int, db: AsyncSession = Depends(get_db)):
    async with db.begin():
        urls = await db.execute(
            select(WebURL).where(WebURL.group_id == group_id).order_by(WebURL.sort_order, WebURL.id))
        urls = urls.scalars().all()

    return simple_response(data=[u for u in urls])


@router.get('/search')
async def search_urls(query: str, db: AsyncSession = Depends(get_db)):
    if not query:
        return simple_response(code=404)

    async with db.begin():
        urls = await db.execute(
            select(WebURL).filter(
                or_(
                    WebURL.description.like(f'%{query}%'),
                    WebURL.name.like(f'%{query}%'),
                    WebURL.icon.like(f'%{query}%')
                )
            )
        )
        urls = urls.scalars().all()

    return simple_response(data=[u for u in urls])
